package com.wengu.algorithm.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wengu.algorithm.alg.QAOTO;
import com.wengu.algorithm.alg.QEA;
import com.wengu.algorithm.alg.QPA;
import com.wengu.algorithm.entity.*;
import com.wengu.algorithm.mapper.AssignmentOutcomeMapper;
import com.wengu.algorithm.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 模拟任务分配结果 服务实现类
 * </p>
 *
 * @author wanghailei
 * @since 2025-02-23
 */
@Slf4j
@Service
public class AssignmentOutcomeServiceImpl extends ServiceImpl<AssignmentOutcomeMapper, AssignmentOutcome> implements AssignmentOutcomeService {

    @Resource
    private TaskArrivalSpatialDistributionService taskArrivalSpatialDistributionService;
    @Resource
    private UserArrivalSpatialDistributionService userArrivalSpatialDistributionService;
    @Resource
    private AssignmentOutcomeUserService assignmentOutcomeUserService;
    @Resource
    private AssignmentOutcomeTaskService assignmentOutcomeTaskService;

    @Override
    public AssignmentOutcome saveOutComeInit(TaskAssignmentScenario taskAssignmentScenario, String algName, QEA alg, String qualityFunction, String weightWay) {
        int taskCount = taskArrivalSpatialDistributionService.count(Wrappers.<TaskArrivalSpatialDistribution>lambdaQuery().eq(TaskArrivalSpatialDistribution::getMainId, taskAssignmentScenario.getId()).eq(TaskArrivalSpatialDistribution::getDeleteFlag,"0"));
        int userCount = userArrivalSpatialDistributionService.count(Wrappers.<UserArrivalSpatialDistribution>lambdaQuery().eq(UserArrivalSpatialDistribution::getMainId, taskAssignmentScenario.getId()).eq(UserArrivalSpatialDistribution::getDeleteFlag,"0"));
        AssignmentOutcome assignmentOutcome = new AssignmentOutcome();
        assignmentOutcome.setMainId(taskAssignmentScenario.getId());
        assignmentOutcome.setVersionNo(taskAssignmentScenario.getVersionNo());
        assignmentOutcome.setCreateDate(new Date());
        assignmentOutcome.setUpdateDate(new Date());
        assignmentOutcome.setDeleteFlag(0);
        assignmentOutcome.setTaskNumber(taskCount);
        assignmentOutcome.setUserNumber(userCount);
        assignmentOutcome.setTotalQuality(0d);
        assignmentOutcome.setAverageQuality(0d);
        assignmentOutcome.setTaskAverageExecuteTimes(0d);
        assignmentOutcome.setAlgName(algName);
        assignmentOutcome.setAlpha(alg.alpha);
        assignmentOutcome.setSigma(alg.sigma);
        assignmentOutcome.setGamma(alg.gamma);
        assignmentOutcome.setMu(alg.mu);
        assignmentOutcome.setBestSelectionProbability(alg.bestSelectionProbability);
        assignmentOutcome.setAntCount(alg.antCount);
        assignmentOutcome.setRoundCount(alg.roundCount);
        assignmentOutcome.setInitialPheromone(alg.initialPheromone);
        assignmentOutcome.setPheromoneWeight(alg.pheromoneWeight);
        assignmentOutcome.setHeuristicWeight(alg.heuristicWeight);
        assignmentOutcome.setEvaporationRate(alg.evaporationRate);
        assignmentOutcome.setQualityFunction(qualityFunction);
        assignmentOutcome.setWeightWay(weightWay);
        this.save(assignmentOutcome);
        return assignmentOutcome;
    }

    @Override
    public void updateQuality(AssignmentOutcome assignmentOutcome) {
        List<AssignmentOutcomeTask> outTaskList = assignmentOutcomeTaskService.list(Wrappers.<AssignmentOutcomeTask>lambdaQuery().eq(AssignmentOutcomeTask::getOutcomeId, assignmentOutcome.getId()));
//        List<AssignmentOutcomeUser> outcomeUserList = assignmentOutcomeUserService.list(Wrappers.<AssignmentOutcomeUser>lambdaQuery().eq(AssignmentOutcomeUser::getOutcomeId, assignmentOutcome.getId()));
        if (!outTaskList.isEmpty()) {
            double totalQualityRound = 0;
            double totalExecuteTimesRound = 0;
            for (AssignmentOutcomeTask assignmentOutcomeTask : outTaskList) {
                totalQualityRound += assignmentOutcomeTask.getTotalQuality();
                totalExecuteTimesRound += assignmentOutcomeTask.getExecuteTimes();
            }
            assignmentOutcome.setTotalQuality(totalQualityRound);
            assignmentOutcome.setAverageQuality(totalQualityRound/assignmentOutcome.getTaskNumber());
            assignmentOutcome.setTaskAverageExecuteTimes(totalExecuteTimesRound/assignmentOutcome.getTaskNumber());
            assignmentOutcome.setUpdateDate(new Date());
            this.updateById(assignmentOutcome);
        }

    }

    @Override
    public AssignmentOutcome saveOutComeInitForQPA(TaskAssignmentScenario taskAssignmentScenario, String algName, QPA alg, String qualityFunction) {
        int taskCount = taskArrivalSpatialDistributionService.count(Wrappers.<TaskArrivalSpatialDistribution>lambdaQuery().eq(TaskArrivalSpatialDistribution::getMainId, taskAssignmentScenario.getId()).eq(TaskArrivalSpatialDistribution::getDeleteFlag,"0"));
        int userCount = userArrivalSpatialDistributionService.count(Wrappers.<UserArrivalSpatialDistribution>lambdaQuery().eq(UserArrivalSpatialDistribution::getMainId, taskAssignmentScenario.getId()).eq(UserArrivalSpatialDistribution::getDeleteFlag,"0"));
        AssignmentOutcome assignmentOutcome = new AssignmentOutcome();
        assignmentOutcome.setMainId(taskAssignmentScenario.getId());
        assignmentOutcome.setVersionNo(taskAssignmentScenario.getVersionNo());
        assignmentOutcome.setCreateDate(new Date());
        assignmentOutcome.setUpdateDate(new Date());
        assignmentOutcome.setDeleteFlag(0);
        assignmentOutcome.setTaskNumber(taskCount);
        assignmentOutcome.setUserNumber(userCount);
        assignmentOutcome.setTotalQuality(0d);
        assignmentOutcome.setAverageQuality(0d);
        assignmentOutcome.setTaskAverageExecuteTimes(0d);
        assignmentOutcome.setAlgName(algName);
        assignmentOutcome.setAlpha(alg.alpha);
        assignmentOutcome.setSigma(alg.sigma);
        assignmentOutcome.setQualityFunction(qualityFunction);
        this.save(assignmentOutcome);
        return assignmentOutcome;
    }

    @Override
    public AssignmentOutcome saveOutComeInit(TaskAssignmentScenario taskAssignmentScenario, String algName, QAOTO alg, String qualityFunction, String weightWay) {
        int taskCount = taskArrivalSpatialDistributionService.count(Wrappers.<TaskArrivalSpatialDistribution>lambdaQuery().eq(TaskArrivalSpatialDistribution::getMainId, taskAssignmentScenario.getId()).eq(TaskArrivalSpatialDistribution::getDeleteFlag,"0"));
        int userCount = userArrivalSpatialDistributionService.count(Wrappers.<UserArrivalSpatialDistribution>lambdaQuery().eq(UserArrivalSpatialDistribution::getMainId, taskAssignmentScenario.getId()).eq(UserArrivalSpatialDistribution::getDeleteFlag,"0"));
        AssignmentOutcome assignmentOutcome = new AssignmentOutcome();
        assignmentOutcome.setMainId(taskAssignmentScenario.getId());
        assignmentOutcome.setVersionNo(taskAssignmentScenario.getVersionNo());
        assignmentOutcome.setCreateDate(new Date());
        assignmentOutcome.setUpdateDate(new Date());
        assignmentOutcome.setDeleteFlag(0);
        assignmentOutcome.setTaskNumber(taskCount);
        assignmentOutcome.setUserNumber(userCount);
        assignmentOutcome.setTotalQuality(0d);
        assignmentOutcome.setAverageQuality(0d);
        assignmentOutcome.setTaskAverageExecuteTimes(0d);
        assignmentOutcome.setAlgName(algName);
        assignmentOutcome.setAlpha(0);
        assignmentOutcome.setSigma(0);
        assignmentOutcome.setQualityFunction(qualityFunction);
        this.save(assignmentOutcome);
        return assignmentOutcome;
    }
}
